/** @file net_dev.h
  *
  * @brief This file contains the net device defines etc
  *
  *  Copyright (C) 2024, Artosyn Technologies. ALL RIGHTS RESERVED.
  *
  *  This Information is proprietary to Artosyn Technologies and MAY NOT
  *  be copied by any method or incorporated into another program without
  *  the express written consent of Artosyn. This Information or any portion
  *  thereof remains the property of Artosyn. The Information contained herein
  *  is believed to be accurate and Artosyn assumes no responsibility or
  *  liability for its use in any way and conveys no license or title under
  *  any patent or copyright and makes no representation or warranty that this
  *  Information is free from patent or copyright infringement.
  *
  */
#ifndef _NET_DEV_H_
#define _NET_DEV_H_

#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
#include "oal_main.h"

/** Align size for net payload */
#define AR_NET_TX_ALIGN_SIZE 4

/** Align size mask for net payload */
#define AR_NET_TX_ALIGN_MASK (AR_NET_TX_ALIGN_SIZE - 1)

/** Watchdog timeout for net device */
#define AR_NET_TX_LIFETIME_MS (1*HZ)

/**
 * AR_NET_TX_MAX_HEADROOM - Maximum size needed in skb headroom to prepare a buffer
 * for transmission
 * The headroom is used to store the RPC header.
 */
#define AR_NET_TX_MAX_HEADROOM (RPC_PACKET_HEADER_LEN + RPC_SOCKET_HEADER_LEN + RPC_SOCKET_DATAGRAM_HEADER_LEN + AR_NET_TX_ALIGN_SIZE)
/**
 * AR_NET_TX_MAX_TAILROOM - Maximum size needed in skb tailroom to prepare a buffer
 * for transmission
 * The tailroom is used to store the RPC header.
 */
#define AR_NET_TX_MAX_TAILROOM (RPC_PACKET_TAILER_LEN + RPC_SOCKET_DATAGRAM_TAILER_LEN + AR_NET_TX_ALIGN_SIZE)

/** Default char dev name of the net devicee */
#define NET_DEV_CDEV_NAME               "ar_net"  /* "ar_net" */

/** Max length of the net device's name */
#define AR_NET_MAX_NET_NAME_LEN         16
/** Length of the eth mac */
#define AR_NET_MAC_LEN                  6

/** Netif type */
#define AR_NET_NETIF_T_PORT             0
#define AR_NET_NETIF_T_VLAN             1

enum ar_net_operate_code_e
{
    AR_NET_OP_CREATE,                   /** Create the net device */
    AR_NET_OP_DESTORY,                  /** Destroy the net device */
    AR_NET_OP_GET,                      /** Get the info of the net device */
    AR_NET_OP_BUF_RESIZE,               /** Resize the rx/tx buffer of the socket */
    AR_NET_OP_MAX,
};
typedef enum ar_net_operate_code_e ar_net_operate_code_t;

/** net dev info for create/destroy/lookup */
typedef struct ar_netif_s
{
    unsigned char op_type;                          /** <@note Operations, refers to AR_NET_OP_xxx */
    unsigned char netif_id;                         /** <@note (OUT)netif id (create or lookup) */
    unsigned char type;                             /** <@note Port/Vlan, refers to AR_NET_NETIF_T_xxx */
    unsigned char slot;                             /** <@note bb socket slot */
    unsigned short vlan;                            /** <@note vlan when type is AR_NET_NETIF_T_VLAN */
    unsigned short socket_port;                     /** <@note bb socket port */
    unsigned char mac[AR_NET_MAC_LEN];              /** <@note mac of the net device */
    unsigned char name[AR_NET_MAX_NET_NAME_LEN];    /** <@note name of the net device */
    unsigned long tx_buf_size;                      /** <@note Tx buffer of the socket */
    unsigned long rx_buf_size;                      /** <@note Rx buffer of the socket */
} __attribute__((__packed__)) ar_netif_t;

/** Version of the net device module */
enum ar_net_version_e
{
    VERSION_MIN,
    VERSION_1DOT0,
    VERSION_1DOT1,
    VERSION_1DOT2,
    VERSION_1DOT3,
    VERSION_1DOT4,

    VERSION_MAX
};

/** Local stats of the net device */
struct ar_netif_stats_s
{
    ktime_t rate_calc_start_time;

    /* TX */
    u64 tx_pkts;                /** total tx packets */
    u64 tx_bytes;               /** total tx bytes */
    /* stats for rate calc */
    u64 tx_pkts_period;
    u64 tx_bytes_period;
    /* rate */
    u32 tx_pkts_rate;           /** tx pkt rate (packet/s) */
    u32 tx_bytes_rate;          /** tx bytes rate (bits/s) */
    u32 tx_pkts_rate_max;       /** max tx pkt rate (packet/s) */
    u32 tx_bytes_rate_max;      /** max tx bytes rate (bits/s) */

    /* RX */
    u64 rx_pkts;                /** total rx packets */
    u64 rx_bytes;               /** total rx bytes */
    /* stats for rate calc */
    u64 rx_pkts_period;         /** rx pkt rate (packet/s) */
    u64 rx_bytes_period;        /** rx bytes rate (bits/s) */
    /* rate */
    u32 rx_pkts_rate;           /** rx pkt rate (packet/s) */
    u32 rx_bytes_rate;          /** rx bytes rate (bits/s) */
    u32 rx_pkts_rate_max;       /** max rx pkt rate (packet/s) */
    u32 rx_bytes_rate_max;      /** max rx bytes rate (bits/s) */
};
typedef struct ar_netif_stats_s ar_netif_stats_t;


/****************************
 * Function declare
 ****************************/

/**
 *  @brief Init the net device module
 *
 *  @param handle  Point to oal_handle
 *
 *  @return        0 for success, otherwise fail
 */
int ar_net_dev_init(oal_handle *handle);

/**
 *  @brief Deinit the net device module
 *
 *  @param handle  Point to oal_handle
 *
 *  @return        N/A
 */
void ar_net_dev_exit(oal_handle *handle);

/**
 *  @brief Push the skb to the list for net device rx
 *
 *  @param handle   Refers to oal_handle.
 *  @param netif    Info of the net device(public)
 *  @param skb      skb receive from bus
 *
 *  @return         0 for success, otherwise fail
 */
int
ar_net_rx_enqueue(oal_handle *handle, ar_netif_t* netif, struct sk_buff *skb);


/**
 *  @brief Whether bb socket bind to netif with flag BB_SOCK_FLAG_DATAGRAM
 *
 *  @param handle   Refers to oal_handle.
 *  @param netif    Info of the net device(public)
 *
 *  @return         true:with flag BB_SOCK_FLAG_DATAGRAM, false:not with
 */
bool ar_net_is_datagram_socket(oal_handle *handle, ar_netif_t *netif);

/**
 *  @brief Whether netif has been create.
 *
 *  @param handle   Refers to oal_handle.
 *  @param netif    Info of the net device(public)
 *
 *  @return         true:created, false:not created
 */
bool ar_net_exists(oal_handle *handle, ar_netif_t *netif);

/** TBD: register the stats get callback */
/**
 *  @brief Get stats of the net device
 *
 *  @param handle   Refers to oal_handle.
 *  @param netif    Info of the net device(public)
 *  @param stats    (OUT)stats of the net device
 *
 *  @return         0 for success, otherwise fail
 */
int ar_net_dev_stats_get(oal_handle *handle, ar_netif_t *netif, ar_netif_stats_t *stats);

/**
 * @brief Process after tx done and wake the netif queue.
 *
 *  @param poal_handle  Point to oal_handle
 *  @param req          skbreq has been tx done
 *
 *  @return             N/A
 */
void ar_net_device_tx_cb(oal_handle *poal_handle, struct ar_skbreq *req);

#endif